import os
!mkdir Data
os.environ['KAGGLE_USERNAME'] = "jackira" # username from the json file
os.environ['KAGGLE_KEY'] = "d268cc116aa8a011c44bc304dc1b83d2" # key from the json file
!kaggle datasets download -d mikaelstrauhs/airbus-ship-detection-train-set-70 -p /content/Data
Downloading airbus-ship-detection-train-set-70.zip to /content/Data 100% 18.5G/18.5G [03:52<00:00, 54.5MB/s] 100% 18.5G/18.5G [03:52<00:00, 85.6MB/s]
import zipfile
fantasy_zip = zipfile.ZipFile('/content/Data/airbus-ship-detection-train-set-70.zip')
fantasy_zip.extractall('/content/Data/')
fantasy_zip.close()
!rm Data/*.zip
BATCH_SIZE = 256
EDGE_CROP = 16
GAUSSIAN_NOISE = 0.1
UPSAMPLE_MODE = "SIMPLE"
#Понижение дискритизации внутри сети
NET_SCALING = (1, 1)
#Понижение размерности в предобработке
IMG_SCALING = (3, 3)
#Число изображений для валидации
VALID_IMG_COUNT = 900
#Максимальное число шагов за эпоху при обучении
MAX_TRAIN_STEPS = 9
MAX_TRAIN_EPOCHS = 20
AUGMENT_BRIGHTNESS = True
SEED = 42
from skimage.util import montage
import os
import numpy as np
import pandas as pd
import tensorflow as tf
from skimage.io import imread
import matplotlib.pyplot as plt
from matplotlib.cm import get_cmap
from skimage.segmentation import mark_boundaries
from sklearn.model_selection import train_test_split
import keras.backend as K
import torch
from keras.preprocessing.image import ImageDataGenerator
from keras import models, layers
import keras.backend as K
from keras.optimizers import Adam
from keras.losses import binary_crossentropy
from keras.callbacks import ModelCheckpoint, LearningRateScheduler, EarlyStopping, ReduceLROnPlateau
from tensorflow.keras.optimizers import RMSprop, Adam
import tensorflow.python.ops.numpy_ops.np_config as np_config
np_config.enable_numpy_behavior()
from skimage.morphology import binary_opening, disk, label
import gc; gc.enable()
from PIL import Image
import keras
print("Tensorflow version: ", tf.__version__)
print("Keras version: ", keras.__version__)
print("Numpy version: ", np.__version__)
gc.enable()
montage_rgb = lambda x: np.stack([montage(x[:, :, :, i]) for i in range(x.shape[3])], -1)
ship_dir = "/content/Data/"
train_image_dir = os.path.join(ship_dir, 'train_v3/train_v3/Images')
def rle_encode(img, min_max_treshold = 1e-3, max_mean_treshold = None):
'''
img: numpy array, 1 - mask, 0 - background
Возвращает бегущую строку как форматированную
'''
if (np.max(img) < min_max_treshold):
return ''
if (max_mean_treshold and np.mean(img) > max_mean_treshold):
return ''
pixels = img.T.flatten()
pixels = np.concatenate([[0], pixels, [0]])
runs = np.where(pixels[1:] != pixels[:-1])[0] + 1
runs[1::2] -= runs[::2]
return ' '.join(str(x) for x in runs)
def multi_rle_encode(img, **kwargs):
'''
Кодируем объединенные регионы как разделители масок
'''
labels = label(img)
if img.ndim > 2:
return [rle_encode(np.sum(labels == k, axis = 2), **kwargs) for k in np.unique(labels[labels > 0])]
else:
return [rle_encode(labels == k, **kwargs) for k in np.unique(labels[labels > 0])]
def rle_decode(mask_rle, shape = (768, 768)):
'''
mask_rle: бегущая - длина как форматированная строка (start length)
shape: (height,width) массив для возвратного значения
Возвращаем numpy array, 1 - mask, 0 - background
'''
s = mask_rle.split()
starts, lengths = [np.asarray(x, dtype = int) for x in (s[0:][::2], s[1:][::2])]
starts -= 1
ends = starts + lengths
img = np.zeros(shape[0] * shape[1], dtype = np.uint8)
for lo, hi in zip(starts, ends):
img[lo:hi] = 1
return img.reshape(shape).T
def masks_as_image(in_mask_list):
#Берем индивидуальную маску корабля и создаем отдельный массив масок для всех кораблей
all_masks = np.zeros((768, 768), dtype = np.uint8)
for mask in in_mask_list:
if isinstance(mask, str):
all_masks |= rle_decode(mask)
return all_masks
def masks_as_color(in_mask_list):
#Берем индивидуальную маску корабля и создаем цветовую маску для каждого корабля
all_masks = np.zeros((768, 768), dtype = np.float)
scale = lambda x: (len(in_mask_list) + x + 1) / (len(in_mask_list) * 2)
for i, mask in enumerate(in_mask_list):
if isinstance(mask, str):
all_masks[:, :] += scale(i) * rle_decode(mask)
return all_masks
masks = pd.read_csv(ship_dir + "train_ship_segmentations_v3.csv")
masks
not_empty = pd.notna(masks.EncodedPixels)
print(not_empty.sum(), "masks in", masks[not_empty].ImageId.nunique(), 'Images')
print((~not_empty).sum(), "empty images in", masks.ImageId.nunique(), "total images")
im_name = os.listdir(train_image_dir)[1]
im = Image.open(train_image_dir + "/" + im_name)
im
fig, (ax0, ax1, ax2, ax3, ax4) = plt.subplots(1, 5, figsize = (30, 5))
rle_0 = masks.query('ImageId == "{0}"'.format(im_name))["EncodedPixels"]
img_0 = masks_as_image(rle_0)
ax0.imshow(im)
ax0.set_title("Оригинальное изображение")
ax1.imshow(img_0)
ax1.set_title("Маска как изображение")
rle_1 = multi_rle_encode(img_0)
img_1 = masks_as_color(rle_0)
ax2.imshow(img_1)
ax2.set_title("Перекодированное")
img_c = masks_as_color(rle_0)
ax3.imshow(img_c)
ax3.set_title("Масква в цвете")
img_c = masks_as_color(rle_1)
ax4.imshow(img_c)
ax4.set_title("Перекодированное в цвета")
print("Проверка Декодирования -> Кодирование", 'RLE_0:', len(rle_0), '->',
'RLE_1:', len(rle_1))
print(np.sum(img_0 - img_1), 'error')
#Поле, указывающее, есть ли корабль на картинке: 1 - есть, 0 - нет
masks['ships'] = masks['EncodedPixels'].map(lambda c_row: 1 if isinstance(c_row, str) else 0)
unique_img_ids = masks.groupby("ImageId").agg({'ships': 'sum'}).reset_index()
unique_img_ids['has_ship'] = unique_img_ids['ships'].map(lambda x: 1.0 if x > 0 else 0.0)
unique_img_ids['has_ship_vec'] = unique_img_ids['has_ship'].map(lambda x: [x])
unique_img_ids['file_size_kb'] = unique_img_ids['ImageId'].map(lambda c_img_id: os.stat(os.path.join(train_image_dir, c_img_id)).st_size/1024)
unique_img_ids['file_size_kb'].hist()
masks.drop(['ships'], axis = 1, inplace = True)
unique_img_ids.sample(10)
unique_img_ids['ships'].hist(bins= unique_img_ids['ships'].max() + 1)
======================== МЕСТО ДЛЯ ОТСЕИВАНИЯ ДУБЛИКАТОВ ===========================
masks['ships'] = masks['EncodedPixels'].map(lambda c_row: 1 if isinstance(c_row, str) else 0)
unique_img_ids = masks.groupby('ImageId').agg({'ships': 'sum'}).reset_index()
unique_img_ids['has_ship'] = unique_img_ids['ships'].map(lambda x: 1.0 if x>0 else 0.0)
unique_img_ids['has_ship_vec'] = unique_img_ids['has_ship'].map(lambda x: [x])
# some files are too small/corrupt
unique_img_ids['file_size_kb'] = unique_img_ids['ImageId'].map(lambda c_img_id:
os.stat(os.path.join(train_image_dir,
c_img_id)).st_size/1024)
unique_img_ids = unique_img_ids[unique_img_ids['file_size_kb'] > 50] # keep only +50kb files
unique_img_ids['file_size_kb'].hist()
masks.drop(['ships'], axis=1, inplace=True)
unique_img_ids.sample(7)
SAMPLES_PER_GROUP = 25000
balanced_train_df = unique_img_ids.groupby('ships').apply(lambda x: x.sample(SAMPLES_PER_GROUP) if len(x) > SAMPLES_PER_GROUP else x)
balanced_train_df['ships'].hist(bins=balanced_train_df['ships'].max()+1)
print(balanced_train_df.shape[0], 'masks')
train_ids, valid_ids = train_test_split(balanced_train_df, test_size = 0.25, random_state = SEED)
train_df = pd.merge(masks, train_ids)
valid_df = pd.merge(masks, valid_ids)
print(train_df.shape[0], 'training masks')
print(valid_df.shape[0], 'validation masks')
'''
train_df = train_df[train_df['has_ship'] == 1.0]
train_df['has_ship'].value_counts()
'''
def make_image_gen(in_df, batch_size = BATCH_SIZE):
all_batches = list(in_df.groupby('ImageId'))
out_rgb = []
out_mask = []
while True:
np.random.shuffle(all_batches)
for c_img_id, c_masks in all_batches:
rgb_path = os.path.join(train_image_dir, c_img_id)
c_img = imread(rgb_path)
c_mask = np.expand_dims(masks_as_image(c_masks['EncodedPixels'].values), -1)
if IMG_SCALING is not None:
c_img = c_img[::IMG_SCALING[0], ::IMG_SCALING[1]]
c_mask = c_mask[::IMG_SCALING[0], ::IMG_SCALING[1]]
out_rgb += [c_img]
out_mask += [c_mask]
if len(out_rgb)>=batch_size:
yield np.stack(out_rgb, 0)/255.0, np.stack(out_mask, 0)
out_rgb, out_mask=[], []
"""
x (2048, 256, 256, 3) 0.0 1.0
y (2048, 256, 256, 1) 0 1
"""
train_gen = make_image_gen(train_df)
train_x, train_y = next(train_gen)
print('x', train_x.shape, train_x.min(), train_x.max())
print('y', train_y.shape, train_y.min(), train_y.max())
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize = (30, 10))
batch_rgb = montage_rgb(train_x)
batch_seg = montage(train_y[:, :, :, 0])
ax1.imshow(batch_rgb)
ax1.set_title('Images')
ax2.imshow(batch_seg)
ax2.set_title('Segmentations')
ax3.imshow(mark_boundaries(batch_rgb,
batch_seg.astype(int)))
ax3.set_title('Outlined Ships')
fig.savefig('overview.png')
%%time
valid_x, valid_y = next(make_image_gen(valid_df, VALID_IMG_COUNT))
print(valid_x.shape, valid_y.shape)
valid_x
valid_x[0]
s = 10
j = 0
for r in valid_y[-17]:
k = 10
i = 0
for c in r:
if(i > k):
print("...")
break;
print(c, sep=' ', end='', flush=True)
i += 1
print
j += 1
if(j > k):
print("...")
break;
dg_args = dict(featurewise_center = False,
samplewise_center = False,
shear_range = 0.01,
zoom_range = [0.9, 1.25],
fill_mode = 'reflect',
data_format = 'channels_last')
# brightness can be problematic since it seems to change the labels differently from the images
if AUGMENT_BRIGHTNESS:
dg_args['brightness_range'] = [0.5, 1.5]
image_gen = ImageDataGenerator(**dg_args)
if AUGMENT_BRIGHTNESS:
dg_args.pop('brightness_range')
label_gen = ImageDataGenerator(**dg_args)
def create_aug_gen(in_gen, seed = None):
np.random.seed(seed if seed is not None else np.random.choice(range(9999)))
for in_x, in_y in in_gen:
seed = np.random.choice(range(9999))
# keep the seeds syncronized otherwise the augmentation to the images is different from the masks
g_x = image_gen.flow(255*in_x,
batch_size = in_x.shape[0],
seed = seed,
shuffle=True)
g_y = label_gen.flow(in_y,
batch_size = in_x.shape[0],
seed = seed,
shuffle=True)
yield next(g_x)/255.0, next(g_y)
"""
x (64, 256, 256, 3) float32 0.0 1.0
y (64, 256, 256, 1) float32 0.0 1.0
"""
cur_gen = create_aug_gen(train_gen)
t_x, t_y = next(cur_gen)
print('x', t_x.shape, t_x.dtype, t_x.min(), t_x.max())
print('y', t_y.shape, t_y.dtype, t_y.min(), t_y.max())
# only keep first 9 samples to examine in detail
t_x = t_x[:9]
t_y = t_y[:9]
fig, (ax1, ax2) = plt.subplots(1, 2, figsize = (20, 10))
ax1.imshow(montage_rgb(t_x), cmap='gray')
ax1.set_title('images')
ax2.imshow(montage(t_y[:, :, :, 0]), cmap='gray_r')
ax2.set_title('ships')
gc.collect()
#https://lars76.github.io/2018/09/27/loss-functions-for-segmentation.html
#https://keras.io/api/metrics/segmentation_metrics/#image-segmentation-metrics
#https://www.kaggle.com/bigironsphere/loss-function-library-keras-pytorch#BCE-Dice-Loss
#https://www.kaggle.com/qiuzy8/focal-tversky-loss
def dice_coef(y_true, y_pred):
y_true = tf.cast(y_true, tf.float64)
y_pred = tf.cast(y_pred, tf.float64)
numerator = 2 * tf.reduce_sum(y_true * y_pred)
denominator = tf.reduce_sum(y_true + y_pred)
return numerator / denominator
def true_positive_rate( y_true, y_pred):
return K.sum(K.flatten(y_true)*K.flatten(K.round(y_pred)))/K.sum(y_true)
def dice_loss(y_true, y_pred):
return 1 - dice_coef( y_true, y_pred)
#Keras
ALPHA = 0.8
GAMMA = 4
def FocalLoss(targets, inputs, alpha=ALPHA, gamma=GAMMA):
y_true = K.cast(targets, 'float64')
y_pred = K.cast(inputs, 'float64')
inputs = K.flatten(y_pred)
targets = K.flatten(y_true)
BCE = K.binary_crossentropy(targets, inputs)
BCE_EXP = K.exp(-BCE)
focal_loss = K.mean(alpha * K.pow((1-BCE_EXP), gamma) * BCE)
return focal_loss
from keras.backend import set_session
from keras.backend import clear_session
from keras.backend import get_session
import tensorflow
# Reset Keras Session
def reset_keras():
sess = get_session()
clear_session()
sess.close()
sess = get_session()
reset_keras()
# Custom Callback To Include in Callbacks List At Training Time
class GarbageCollectorCallback(tf.keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs=None):
gc.collect()
reset_keras()
def on_train_batch_begin(self, batch, logs=None):
reset_keras()
def on_train_batch_end(self, batch, logs=None):
reset_keras()
def on_test_batch_begin(self, batch, logs=None):
reset_keras()
def on_test_batch_end(self, batch, logs=None):
reset_keras()
def GetUnetModel():
# Build U-Net model
def upsample_conv(filters, kernel_size, strides, padding):
return layers.Conv2DTranspose(filters, kernel_size, strides=strides, padding=padding)
def upsample_simple(filters, kernel_size, strides, padding):
return layers.UpSampling2D(strides)
if UPSAMPLE_MODE=='DECONV':
upsample=upsample_conv
else:
upsample=upsample_simple
input_img = layers.Input(t_x.shape[1:], name = 'RGB_Input')
pp_in_layer = input_img
if NET_SCALING is not None:
pp_in_layer = layers.AvgPool2D(NET_SCALING)(pp_in_layer)
pp_in_layer = layers.GaussianNoise(GAUSSIAN_NOISE)(pp_in_layer)
pp_in_layer = layers.BatchNormalization()(pp_in_layer)
filter_num = 8
c1 = layers.Conv2D(filter_num, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (pp_in_layer)
c1 = layers.Conv2D(filter_num, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (c1)
p1 = layers.MaxPooling2D((2, 2)) (c1)
c2 = layers.Conv2D(filter_num*2, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (p1)
c2 = layers.Conv2D(filter_num*2, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (c2)
p2 = layers.MaxPooling2D((2, 2)) (c2)
c3 = layers.Conv2D(filter_num*4, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (p2)
c3 = layers.Conv2D(filter_num*4, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (c3)
p3 = layers.MaxPooling2D((2, 2)) (c3)
c4 = layers.Conv2D(filter_num*8, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (p3)
c4 = layers.Conv2D(filter_num*8, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (c4)
p4 = layers.MaxPooling2D(pool_size=(2, 2)) (c4)
c5 = layers.Conv2D(filter_num*16, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (p4)
c5 = layers.Conv2D(filter_num*16, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (c5)
u6 = upsample(filter_num*8, (2, 2), strides=(2, 2), padding='same') (c5)
u6 = layers.concatenate([u6, c4])
c6 = layers.Conv2D(filter_num*8, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (u6)
c6 = layers.Conv2D(filter_num*8, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (c6)
u7 = upsample(filter_num*4, (2, 2), strides=(2, 2), padding='same') (c6)
u7 = layers.concatenate([u7, c3])
c7 = layers.Conv2D(filter_num*4, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (u7)
c7 = layers.Conv2D(filter_num*4, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (c7)
u8 = upsample(filter_num*2, (2, 2), strides=(2, 2), padding='same') (c7)
u8 = layers.concatenate([u8, c2])
c8 = layers.Conv2D(filter_num*2, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (u8)
c8 = layers.Conv2D(filter_num*2, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (c8)
u9 = upsample(filter_num, (2, 2), strides=(2, 2), padding='same') (c8)
u9 = layers.concatenate([u9, c1], axis=3)
c9 = layers.Conv2D(filter_num, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (u9)
c9 = layers.Conv2D(filter_num, (3, 3), kernel_initializer='glorot_normal', activation='relu', padding='same') (c9)
d = layers.Conv2D(1, (1, 1), kernel_initializer='glorot_normal', activation='sigmoid')(c9)
# d = layers.Cropping2D((EDGE_CROP, EDGE_CROP))(d)
# d = layers.ZeroPadding2D((EDGE_CROP, EDGE_CROP))(d)
if NET_SCALING is not None:
d = layers.UpSampling2D(NET_SCALING)(d)
# d = layers.Cropping2D((EDGE_CROP, EDGE_CROP))(d)
# d = layers.ZeroPadding2D((EDGE_CROP, EDGE_CROP))(d)
if NET_SCALING is not None:
d = layers.UpSampling2D(NET_SCALING)(d)
return models.Model(inputs=[input_img], outputs=[d])
def GetSegNetModel(input_shape, n_labels = 1, kernel=3, pool_size=(2, 2), output_mode="softmax"):
import keras.models as models
from keras.layers.core import Layer, Dense, Dropout, Activation, Flatten, Reshape, Permute
from keras.layers.convolutional import MaxPooling2D, UpSampling2D, ZeroPadding2D
from keras.layers.normalization import BatchNormalization
from keras import layers
#merged = Concatenate()([x1, x2])
from keras import backend as K
import cv2
import numpy as np
import json
np.random.seed(7) # 0bserver07 for reproducibility
data_shape = input_shape[0] * input_shape[1]
img_w = input_shape[0]
img_h = input_shape[1]
n_labels = 1
kernel = 3
pad = 1
pool_size = 2
filt_num = 8
encoding_layers = [
layers.Conv2D(filt_num, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
MaxPooling2D(pool_size=(pool_size, pool_size)),
layers.Conv2D(filt_num*2, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num*2, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
MaxPooling2D(pool_size=(pool_size, pool_size)),
layers.Conv2D(filt_num*4, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num*4, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num*4, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
MaxPooling2D(pool_size=(pool_size, pool_size)),
layers.Conv2D(filt_num*8, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num*8, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num*8, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
MaxPooling2D(pool_size=(pool_size, pool_size)),
layers.Conv2D(filt_num*16, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num*16, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num*16, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
MaxPooling2D(pool_size=(pool_size, pool_size)),
]
decoding_layers = [
UpSampling2D(size=(pool_size,pool_size)),
layers.Conv2D(filt_num*16, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num*16, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num*16, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
UpSampling2D(size=(pool_size,pool_size)),
layers.Conv2D(filt_num*8, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num*8, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num*8, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
UpSampling2D(size=(pool_size,pool_size)),
layers.Conv2D(filt_num*4, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num*4, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num*4, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
UpSampling2D(size=(pool_size,pool_size)),
layers.Conv2D(filt_num*2, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(filt_num*2, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
UpSampling2D(size=(pool_size,pool_size)),
layers.Conv2D(filt_num, (kernel, kernel), activation='relu', padding='same'),
BatchNormalization(),
layers.Conv2D(1, (kernel, kernel), activation='relu', padding='valid'),
BatchNormalization(),
]
segnet_basic = models.Sequential()
segnet_basic.add(Layer(input_shape= input_shape))
segnet_basic.encoding_layers = encoding_layers
for l in segnet_basic.encoding_layers:
segnet_basic.add(l)
segnet_basic.decoding_layers = decoding_layers
for l in segnet_basic.decoding_layers:
segnet_basic.add(l)
segnet_basic.add(layers.Conv2D(1, 1, 1, activation = "sigmoid"))
return segnet_basic
from keras.models import load_model
model_pract = load_model('/content/drive/MyDrive/Диплом/Ship_detection/CNN_PRACT/model.h5')
model_pract.summary()
from keras.layers import *
from keras.models import Model
def FCN_Vgg16(input_shape=None, weight_decay=0., batch_momentum=0.9, batch_shape=None, classes=1):
# creating the final model
kernel_s = (2, 2)
img_input = Input(shape=input_shape)
image_size = input_shape[0:2]
filt = 64
dense_unit = 1024
#1
x = Conv2D(filters = filt, kernel_size = kernel_s, padding = 'Same', activation ='relu', trainable = False, weights = model_pract.get_layer(index = 0).get_weights())(img_input)
x = Conv2D(filters = filt, kernel_size = kernel_s, padding = 'Same', activation ='relu', trainable = False, weights = model_pract.get_layer(index = 1).get_weights())(x)
p1 = MaxPool2D((2, 2), strides=(2, 2), name='block1_pool')(x)
#2
x = Conv2D(filters = filt * 2, kernel_size = kernel_s, padding = 'Same', activation ='relu', trainable = False, weights = model_pract.get_layer(index = 3).get_weights())(p1)
x = Conv2D(filters = filt * 2, kernel_size = kernel_s, padding = 'Same', activation ='relu', trainable = False, weights = model_pract.get_layer(index = 4).get_weights())(x)
p2 = MaxPool2D((2, 2), strides=(2, 2), name='block2_pool')(x)
#3
x = Conv2D(filters = filt * 4, kernel_size = kernel_s, padding = 'Same', activation ='relu', trainable = False, weights = model_pract.get_layer(index = 6).get_weights())(p2)
x = Conv2D(filters = filt * 4, kernel_size = kernel_s, padding = 'Same', activation ='relu', trainable = False, weights = model_pract.get_layer(index = 7).get_weights())(x)
x = Conv2D(filters = filt * 4, kernel_size = kernel_s, padding = 'Same', activation ='relu', trainable = False, weights = model_pract.get_layer(index = 8).get_weights())(x)
p3 = MaxPool2D((2, 2), strides=(2, 2), name='block3_pool')(x)
#4
x = Conv2D(filters = filt * 8, kernel_size = kernel_s, padding = 'Same', activation ='relu', trainable = False, weights = model_pract.get_layer(index = 10).get_weights())(p3)
x = Conv2D(filters = filt * 8, kernel_size = kernel_s, padding = 'Same', activation ='relu', trainable = False, weights = model_pract.get_layer(index = 11).get_weights())(x)
x = Conv2D(filters = filt * 8, kernel_size = kernel_s, padding = 'Same', activation ='relu', trainable = False, weights = model_pract.get_layer(index = 12).get_weights())(x)
p4 = MaxPool2D((2, 2), strides=(2, 2), name='block4_pool')(x)
#5
x = Conv2D(filters = filt * 8, kernel_size = kernel_s, padding = 'Same', activation ='relu', trainable = False, weights = model_pract.get_layer(index = 14).get_weights())(p4)
x = Conv2D(filters = filt * 8, kernel_size = kernel_s, padding = 'Same', activation ='relu', trainable = False, weights = model_pract.get_layer(index = 15).get_weights())(x)
x = Conv2D(filters = filt * 8, kernel_size = kernel_s, padding = 'Same', activation ='relu', trainable = False, weights = model_pract.get_layer(index = 16).get_weights())(x)
p5 = MaxPool2D((2, 2), strides=(2, 2), name='block5_pool')(x)
#6
# Convolutional layers transfered from fully-connected layers
x = Conv2D(filt*16, (7, 7), kernel_initializer='glorot_normal', activation='relu', padding='same', name='fc1')(x)
x = Dropout(0.25)(x)
x = Conv2D(filt*16, (1, 1), kernel_initializer='glorot_normal', activation='relu', padding='same', name='fc2')(x)
x = Dropout(0.25)(x)
#classifying layer
#x = Conv2D(classes, (1, 1), kernel_initializer='he_normal', activation='linear', padding='valid', strides=(1, 1))(x)
x = Conv2D(classes, (1, 1), kernel_initializer='glorot_normal', activation='sigmoid', padding='valid', strides=(1, 1))(x)
x = layers.UpSampling2D(size=(16, 16), interpolation = 'bilinear')(x)
model = Model(img_input, x)
return model
weight_path="/content/drive/MyDrive/Диплом/Ship_detection/weights/u_net/{}_weights.best.hdf5".format('FULL_seg_model_dice_loss_RMS')
checkpoint = ModelCheckpoint(weight_path, monitor='val_loss', verbose=1, save_best_only=True, mode='min', save_weights_only=True)
reduceLROnPlat = ReduceLROnPlateau(monitor='val_loss', factor=0.33,
patience=1, verbose=1, mode='min',
min_delta=0.0001, cooldown=0, min_lr=1e-8)
early = EarlyStopping(monitor="val_loss", mode="min", verbose=2,
patience=20) # probably needs to be more patient, but kaggle time is limited
callbacks_list = [checkpoint, early, GarbageCollectorCallback(), reduceLROnPlat]#, reduceLROnPlat]
RMS = RMSprop( learning_rate=0.001,
rho=0.9,
momentum=0.0,
epsilon=1e-07,
centered=False,
name="RMSprop")
adam = Adam(learning_rate=0.001,
beta_1=0.9,
beta_2=0.999,
epsilon=1e-07,
amsgrad=False,
name="Adam")
seg_model = GetUnetModel()
seg_model.compile(optimizer = RMS, loss= dice_loss, metrics=['binary_accuracy', dice_coef, true_positive_rate])
#weight_path1="/content/drive/MyDrive/Диплом/Ship_detection/weights/u_net/{}_weights.best.hdf5".format('seg_model')
#seg_model.load_weights(weight_path)
seg_model.summary()
image_file = 'model_1.png'
tf.keras.utils.plot_model(seg_model, to_file = image_file, show_shapes = True)
gc.collect()
step_count = MAX_TRAIN_STEPS
step_count = train_df.shape[0]//BATCH_SIZE
print("step_count = ", step_count)
aug_gen = create_aug_gen(make_image_gen(train_df))
loss_history = [seg_model.fit(aug_gen,
steps_per_epoch=step_count,
#batch_size = BATCH_SIZE,
epochs=MAX_TRAIN_EPOCHS,
validation_data=(valid_x, valid_y),
callbacks=callbacks_list
)]
Epoch 1/20 238/238 [==============================] - 1909s 8s/step - loss: 0.9962 - binary_accuracy: 0.9676 - dice_coef: 0.0038 - true_positive_rate: 0.0569 - val_loss: 1.0000 - val_binary_accuracy: 0.9975 - val_dice_coef: 2.0790e-07 - val_true_positive_rate: 0.0000e+00 Epoch 00001: val_loss improved from inf to 1.00000, saving model to /content/drive/MyDrive/Диплом/Ship_detection/weights/u_net/FULL_seg_model_dice_loss_RMS_weights.best.hdf5 Epoch 2/20 238/238 [==============================] - 1823s 8s/step - loss: 0.9414 - binary_accuracy: 0.9323 - dice_coef: 0.0586 - true_positive_rate: 0.1623 - val_loss: 0.6106 - val_binary_accuracy: 0.9973 - val_dice_coef: 0.3912 - val_true_positive_rate: 0.3780 Epoch 00002: val_loss improved from 1.00000 to 0.61056, saving model to /content/drive/MyDrive/Диплом/Ship_detection/weights/u_net/FULL_seg_model_dice_loss_RMS_weights.best.hdf5 Epoch 3/20 238/238 [==============================] - 1793s 8s/step - loss: 0.7221 - binary_accuracy: 0.9952 - dice_coef: 0.2779 - true_positive_rate: 0.3089 - val_loss: 0.5482 - val_binary_accuracy: 0.9968 - val_dice_coef: 0.4453 - val_true_positive_rate: 0.5446 Epoch 00003: val_loss improved from 0.61056 to 0.54816, saving model to /content/drive/MyDrive/Диплом/Ship_detection/weights/u_net/FULL_seg_model_dice_loss_RMS_weights.best.hdf5 Epoch 4/20 238/238 [==============================] - 1786s 8s/step - loss: 0.6904 - binary_accuracy: 0.9956 - dice_coef: 0.3096 - true_positive_rate: 0.3336 - val_loss: 0.5042 - val_binary_accuracy: 0.9969 - val_dice_coef: 0.4858 - val_true_positive_rate: 0.6495 Epoch 00004: val_loss improved from 0.54816 to 0.50416, saving model to /content/drive/MyDrive/Диплом/Ship_detection/weights/u_net/FULL_seg_model_dice_loss_RMS_weights.best.hdf5 Epoch 5/20 238/238 [==============================] - 1796s 8s/step - loss: 0.6716 - binary_accuracy: 0.9958 - dice_coef: 0.3284 - true_positive_rate: 0.3467 - val_loss: 0.4613 - val_binary_accuracy: 0.9973 - val_dice_coef: 0.5282 - val_true_positive_rate: 0.6676 Epoch 00005: val_loss improved from 0.50416 to 0.46135, saving model to /content/drive/MyDrive/Диплом/Ship_detection/weights/u_net/FULL_seg_model_dice_loss_RMS_weights.best.hdf5 Epoch 6/20 238/238 [==============================] - 1793s 8s/step - loss: 0.6571 - binary_accuracy: 0.9959 - dice_coef: 0.3429 - true_positive_rate: 0.3676 - val_loss: 0.5021 - val_binary_accuracy: 0.9966 - val_dice_coef: 0.4960 - val_true_positive_rate: 0.7094 Epoch 00006: val_loss did not improve from 0.46135 Epoch 00006: ReduceLROnPlateau reducing learning rate to 0.00033000001567415896. Epoch 7/20 238/238 [==============================] - 1795s 8s/step - loss: 0.6284 - binary_accuracy: 0.9960 - dice_coef: 0.3716 - true_positive_rate: 0.3929 - val_loss: 0.4770 - val_binary_accuracy: 0.9970 - val_dice_coef: 0.5213 - val_true_positive_rate: 0.7107 Epoch 00007: val_loss did not improve from 0.46135 Epoch 00007: ReduceLROnPlateau reducing learning rate to 0.00010890000325161964. Epoch 8/20 238/238 [==============================] - 1796s 8s/step - loss: 0.6140 - binary_accuracy: 0.9961 - dice_coef: 0.3860 - true_positive_rate: 0.4037 - val_loss: 0.4852 - val_binary_accuracy: 0.9968 - val_dice_coef: 0.5076 - val_true_positive_rate: 0.7185 Epoch 00008: val_loss did not improve from 0.46135 Epoch 00008: ReduceLROnPlateau reducing learning rate to 3.5936999920522795e-05. Epoch 9/20 238/238 [==============================] - 1799s 8s/step - loss: 0.6142 - binary_accuracy: 0.9961 - dice_coef: 0.3858 - true_positive_rate: 0.4091 - val_loss: 0.4618 - val_binary_accuracy: 0.9972 - val_dice_coef: 0.5357 - val_true_positive_rate: 0.7065 Epoch 00009: val_loss did not improve from 0.46135 Epoch 00009: ReduceLROnPlateau reducing learning rate to 1.185920958960196e-05. Epoch 10/20 238/238 [==============================] - 1803s 8s/step - loss: 0.6157 - binary_accuracy: 0.9961 - dice_coef: 0.3843 - true_positive_rate: 0.4057 - val_loss: 0.4526 - val_binary_accuracy: 0.9973 - val_dice_coef: 0.5448 - val_true_positive_rate: 0.6995 Epoch 00010: val_loss improved from 0.46135 to 0.45262, saving model to /content/drive/MyDrive/Диплом/Ship_detection/weights/u_net/FULL_seg_model_dice_loss_RMS_weights.best.hdf5 Epoch 11/20 238/238 [==============================] - 1803s 8s/step - loss: 0.6114 - binary_accuracy: 0.9962 - dice_coef: 0.3886 - true_positive_rate: 0.4022 - val_loss: 0.4539 - val_binary_accuracy: 0.9973 - val_dice_coef: 0.5435 - val_true_positive_rate: 0.7024 Epoch 00011: val_loss did not improve from 0.45262 Epoch 00011: ReduceLROnPlateau reducing learning rate to 3.913539212589967e-06. Epoch 12/20 238/238 [==============================] - 1797s 8s/step - loss: 0.6121 - binary_accuracy: 0.9962 - dice_coef: 0.3879 - true_positive_rate: 0.4056 - val_loss: 0.4553 - val_binary_accuracy: 0.9972 - val_dice_coef: 0.5420 - val_true_positive_rate: 0.7054 Epoch 00012: val_loss did not improve from 0.45262 Epoch 00012: ReduceLROnPlateau reducing learning rate to 1.2914679791720119e-06. Epoch 13/20 238/238 [==============================] - 1815s 8s/step - loss: 0.6091 - binary_accuracy: 0.9961 - dice_coef: 0.3909 - true_positive_rate: 0.4116 - val_loss: 0.4577 - val_binary_accuracy: 0.9972 - val_dice_coef: 0.5396 - val_true_positive_rate: 0.7058 Epoch 00013: val_loss did not improve from 0.45262 Epoch 00013: ReduceLROnPlateau reducing learning rate to 4.2618441511876884e-07. Epoch 14/20 238/238 [==============================] - 1796s 8s/step - loss: 0.6053 - binary_accuracy: 0.9961 - dice_coef: 0.3947 - true_positive_rate: 0.4166 - val_loss: 0.4554 - val_binary_accuracy: 0.9972 - val_dice_coef: 0.5420 - val_true_positive_rate: 0.7052 Epoch 00014: val_loss did not improve from 0.45262 Epoch 00014: ReduceLROnPlateau reducing learning rate to 1.4064085661402716e-07. Epoch 15/20 238/238 [==============================] - 1793s 8s/step - loss: 0.6101 - binary_accuracy: 0.9961 - dice_coef: 0.3899 - true_positive_rate: 0.4136 - val_loss: 0.4560 - val_binary_accuracy: 0.9972 - val_dice_coef: 0.5413 - val_true_positive_rate: 0.7055 Epoch 00015: val_loss did not improve from 0.45262 Epoch 00015: ReduceLROnPlateau reducing learning rate to 4.641148052542121e-08. Epoch 16/20 238/238 [==============================] - 1795s 8s/step - loss: 0.6195 - binary_accuracy: 0.9961 - dice_coef: 0.3805 - true_positive_rate: 0.3988 - val_loss: 0.4562 - val_binary_accuracy: 0.9972 - val_dice_coef: 0.5411 - val_true_positive_rate: 0.7060 Epoch 00016: val_loss did not improve from 0.45262 Epoch 00016: ReduceLROnPlateau reducing learning rate to 1.5315788104430796e-08. Epoch 17/20 238/238 [==============================] - 1795s 8s/step - loss: 0.6121 - binary_accuracy: 0.9961 - dice_coef: 0.3879 - true_positive_rate: 0.4067 - val_loss: 0.4543 - val_binary_accuracy: 0.9973 - val_dice_coef: 0.5431 - val_true_positive_rate: 0.7046 Epoch 00017: val_loss did not improve from 0.45262 Epoch 00017: ReduceLROnPlateau reducing learning rate to 1e-08. Epoch 18/20 238/238 [==============================] - 1794s 8s/step - loss: 0.6067 - binary_accuracy: 0.9961 - dice_coef: 0.3933 - true_positive_rate: 0.4163 - val_loss: 0.4567 - val_binary_accuracy: 0.9972 - val_dice_coef: 0.5406 - val_true_positive_rate: 0.7064 Epoch 00018: val_loss did not improve from 0.45262 Epoch 19/20 238/238 [==============================] - 1794s 8s/step - loss: 0.6152 - binary_accuracy: 0.9961 - dice_coef: 0.3848 - true_positive_rate: 0.4049 - val_loss: 0.4571 - val_binary_accuracy: 0.9972 - val_dice_coef: 0.5402 - val_true_positive_rate: 0.7066 Epoch 00019: val_loss did not improve from 0.45262 Epoch 20/20 238/238 [==============================] - 1795s 8s/step - loss: 0.6092 - binary_accuracy: 0.9961 - dice_coef: 0.3908 - true_positive_rate: 0.4107 - val_loss: 0.4563 - val_binary_accuracy: 0.9972 - val_dice_coef: 0.5410 - val_true_positive_rate: 0.7058 Epoch 00020: val_loss did not improve from 0.45262
def show_loss(loss_history):
epochs = np.concatenate([mh.epoch for mh in loss_history])
fig, (ax1, ax2, ax3, ax4) = plt.subplots(1, 4, figsize=(22, 10))
_ = ax1.plot(epochs, np.concatenate([mh.history['loss'] for mh in loss_history]), 'b-',
epochs, np.concatenate([mh.history['val_loss'] for mh in loss_history]), 'r-')
ax1.legend(['Training', 'Validation'])
ax1.set_title('Loss')
_ = ax2.plot(epochs, np.concatenate([mh.history['binary_accuracy'] for mh in loss_history]), 'b-',
epochs, np.concatenate([mh.history['val_binary_accuracy'] for mh in loss_history]), 'r-')
ax2.legend(['Training', 'Validation'])
ax2.set_title('Binary Accuracy (%)')
_ = ax3.plot(epochs, np.concatenate([mh.history['dice_coef'] for mh in loss_history]), 'b-',
epochs, np.concatenate([mh.history['val_dice_coef'] for mh in loss_history]), 'r-')
ax3.legend(['Training', 'Validation'])
ax3.set_title('DICE Coefficient (%)')
_ = ax4.plot(epochs, np.concatenate([mh.history['true_positive_rate'] for mh in loss_history]), 'b-',
epochs, np.concatenate([mh.history['val_true_positive_rate'] for mh in loss_history]), 'r-')
ax4.legend(['Training', 'Validation'])
ax4.set_title('TFP')
fig.savefig('/content/drive/MyDrive/Диплом/Ship_detection/FULL_UNET_dice_loss_RMS_hist.png')
show_loss(loss_history)
gc.collect()
10971
seg_model.load_weights(weight_path)
seg_model.save('/content/drive/MyDrive/Диплом/Ship_detection/weights/u_net/FULL_seg_dice_loss_RMS_model.h5')
pred_y = seg_model.predict(valid_x)
print(pred_y.shape, pred_y.min(axis=0).max(), pred_y.max(axis=0).min(), pred_y.mean())
(900, 256, 256, 1) 0.0 9.827596e-15 0.0037862973
fig, ax = plt.subplots(1, 1, figsize = (6, 6))
ax.hist(pred_y.ravel(), np.linspace(0, 1, 20))
ax.set_xlim(0, 1)
ax.set_yscale('log', nonposy='clip')
if IMG_SCALING is not None:
fullres_model = models.Sequential()
fullres_model.add(layers.AvgPool2D(IMG_SCALING, input_shape = (None, None, 3)))
fullres_model.add(seg_model)
fullres_model.add(layers.UpSampling2D(IMG_SCALING))
else:
fullres_model = seg_model
fullres_model.save('/content/drive/MyDrive/Диплом/Ship_detection/weights/u_net/FULL_fullres_dice_loss_RMS_model.h5')
WARNING:tensorflow:Compiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.
gc.collect()
5105
def raw_prediction(img, path=train_image_dir):
c_img = imread(os.path.join(path, c_img_name))
c_img = np.expand_dims(c_img, 0)/255.0
cur_seg = fullres_model.predict(c_img)[0]
return cur_seg, c_img[0]
def smooth(cur_seg):
return binary_opening(cur_seg>0.5, np.expand_dims(disk(2), -1))
def predict(img, path=train_image_dir):
cur_seg, c_img = raw_prediction(img, path=path)
return smooth(cur_seg), c_img
## Get a sample of each group of ship count
n_samples = 10
samples = valid_df.groupby('ships').apply(lambda x: x.sample(n_samples, random_state = SEED, replace= False))
fig, m_axs = plt.subplots(samples.shape[0], 4, figsize = (15, samples.shape[0]*4))
[c_ax.axis('off') for c_ax in m_axs.flatten()]
for (ax1, ax2, ax3, ax4), c_img_name in zip(m_axs, samples.ImageId.values):
first_seg, first_img = raw_prediction(c_img_name, train_image_dir)
ax1.imshow(first_img)
ax1.set_title('Image: ' + c_img_name)
ax2.imshow(first_seg[:, :, 0], cmap=get_cmap('jet'))
ax2.set_title('Model Prediction')
reencoded = masks_as_color(multi_rle_encode(smooth(first_seg)[:, :, 0]))
ax3.imshow(reencoded)
ax3.set_title('Prediction Masks')
ground_truth = masks_as_color(masks.query('ImageId=="{}"'.format(c_img_name))['EncodedPixels'])
ax4.imshow(ground_truth)
ax4.set_title('Ground Truth')
fig.savefig('/content/drive/MyDrive/Диплом/Ship_detection/FULL_UNET_dice_loss_RMS.png')
plt.show()